﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Grid;
using System.IO;
using System.Threading;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraEditors.ViewInfo;
using DevExpress.XtraEditors.Drawing;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using System.Collections;
using DevExpress.XtraGrid.Menu;
using DevExpress.Utils.Menu;
using DevExpress.XtraGrid.Export;
using DevExpress.XtraExport;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Base;

using DevExpress.XtraPrinting;
using Pharmacy.Ultilities;
using PharmacyPharnet.Core.CustomEventArgs;
using Pharmacy.ExceptionHandling;

namespace PharmacyPharnet.Core
{
    public partial class UCMyGrid : GridControl
    {
        private bool _useCustomFilter = false;
        #region Contructors
        public UCMyGrid()
        {
            InitializeComponent();
            // TODO: Add any initialization after the InitForm call
            //this.LostFocus += new EventHandler(MyGridControl_LostFocus);
            this.Load += new EventHandler(MyGridControl_Load);

            _CURRENTDIRECTORY = IOHelper.CombinePath(IOHelper.ExecutePath, string.Format(@"GridLayouts\{0}", Thread.CurrentPrincipal.Identity.Name));
        }
        #endregion

        #region Attributes
        string _CURRENTDIRECTORY = "";
        string _FormName = "";

        public GridView gvControl;
        RepositoryItemCheckEdit edit = new RepositoryItemCheckEdit();
        RepositoryItemPictureEdit imageResetLayout = new RepositoryItemPictureEdit();
        bool checkboxState = false;
        bool isDisplayCheckBox = true;
        string columnFieldNameAddCheckBox = "";
        string featureName = "";
        bool isSaveLayout = true;

        int minCheckBoxAllX = 0;
        int minCheckBoxAllY = 0;
        int maxCheckBoxAllX = 0;
        int maxCheckBoxAllY = 0;

        int minImageResetX = 0;
        int minImageResetY = 0;
        int maxImageResetX = 0;
        int maxImageResetY = 0;

        Hashtable listStreamLayout;

        public delegate void OnCheckAllChangedStatus(object sender, CheckArgs e);
        public event OnCheckAllChangedStatus CheckAllChangedStatus;
        public event RowIndicatorCustomDrawEventHandler CustomDrawRowIndicator;
        public event EventHandler GridLoad;
        #endregion

        #region Properties
        public bool IsDisplayCheckBox
        {
            get
            {
                return isDisplayCheckBox;
            }
            set { isDisplayCheckBox = value; }
        }

        public bool CheckAllStatus
        {
            get { return checkboxState; }
            set
            {
                checkboxState = value;
                if (CheckAllChangedStatus != null)
                {
                    CheckArgs e = new CheckArgs(checkboxState);
                    CheckAllChangedStatus(edit, e);
                }
            }
        }

        public string ColumnFieldNameCheckBox
        {
            get { return columnFieldNameAddCheckBox; }
            set { columnFieldNameAddCheckBox = value; }
        }

        public RepositoryItemCheckEdit MyCheckBox
        {
            get { return edit; }
        }

        public bool IsSaveLayout
        {
            get { return isSaveLayout; }
            set { isSaveLayout = value; }
        }

        [Browsable(true)]
        public bool UseCustomFilterDialog
        {
            get { return _useCustomFilter; }
            set { _useCustomFilter = value; }
        }

        public string ViewNameGrid
        {
            get { return this.MainView.BaseInfo.ViewName; }
        }
        #endregion

        #region Methods
        void GetFormName()
        {
            try
            {
                DialogViewBase frm = ((GridControl)(this)).FindForm() as DialogViewBase;
                if (frm != null)
                {
                    string name = frm.Name;
                    string[] temp = name.Split(".".ToCharArray());
                    if (frm.ControlViewBase != null)
                        featureName = frm.ControlViewBase.FeatureTypeName;
                    else
                        featureName = frm.FeatureTypeName;
                    if (temp.Length > 0)
                        _FormName = featureName + "_" + temp[temp.Length - 1];
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Có lỗi xảy ra. Vui lòng liên hệ Người quản trị hệ thống để được hỗ trợ.");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
        }

        void SaveLayout()
        {
            try
            {
                ViewManager.CreateWaitDialog();
                ViewManager.SetWaitDialogCaption("Saving Layout...");
                if (!Directory.Exists(_CURRENTDIRECTORY))
                    Directory.CreateDirectory(_CURRENTDIRECTORY);
                foreach (BaseView grv in this.ViewCollection)
                {
                    grv.SaveLayoutToXml(IOHelper.CombinePath(_CURRENTDIRECTORY, String.Format("{0}_{1}.xml", _FormName, grv.Name)));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Có lỗi xảy ra. Vui lòng liên hệ Người quản trị hệ thống để được hỗ trợ.");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
            finally
            {
                ViewManager.CloseWaitDialog();
            }
        }

        void DrawCheckBox(Graphics g, Rectangle r, bool checkedState)
        {
            try
            {
                CheckEditViewInfo info;
                CheckEditPainter painter;
                ControlGraphicsInfoArgs args;
                info = edit.CreateViewInfo() as CheckEditViewInfo;
                painter = edit.CreatePainter() as CheckEditPainter;
                info.EditValue = checkedState;
                info.Bounds = r;
                info.CalcViewInfo(g);
                minCheckBoxAllX = info.CheckInfo.GlyphRect.X;
                minCheckBoxAllY = info.CheckInfo.GlyphRect.Y;
                maxCheckBoxAllX = minCheckBoxAllX + info.CheckInfo.GlyphRect.Size.Width;
                maxCheckBoxAllY = minCheckBoxAllY + info.CheckInfo.GlyphRect.Size.Height;
                args = new ControlGraphicsInfoArgs(info, new DevExpress.Utils.Drawing.GraphicsCache(g), r);
                painter.Draw(args);
                args.Cache.Dispose();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Có lỗi xảy ra. Vui lòng liên hệ Người quản trị hệ thống để được hỗ trợ.");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
        }

        void DrawImageResetLayout(Graphics g, Rectangle r)
        {
            try
            {
                PictureEditViewInfo info;
                PictureEditPainter painter;
                ControlGraphicsInfoArgs args;
                info = imageResetLayout.CreateViewInfo() as PictureEditViewInfo;
                painter = imageResetLayout.CreatePainter() as PictureEditPainter;
                Image img = Image.FromFile(IOHelper.CombinePath(IOHelper.ExecutePath, @"Images\refresh.png"));
                info.Image = img.GetThumbnailImage(18,18, null, IntPtr.Zero);
                info.Bounds = r;
                info.CalcViewInfo(g);
                minImageResetX = info.PictureStartX;
                minImageResetY = info.PictureStartY;
                maxImageResetX = minImageResetX + info.Image.Size.Width;
                maxImageResetY = minImageResetY + info.Image.Size.Height;
                args = new ControlGraphicsInfoArgs(info, new DevExpress.Utils.Drawing.GraphicsCache(g), r);
                painter.Draw(args);
                args.Cache.Dispose();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Có lỗi xảy ra. Vui lòng liên hệ Người quản trị hệ thống để được hỗ trợ.");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
        }

        void ResetLayout()
        {
            try
            {
                ViewManager.CreateWaitDialog();
                ViewManager.SetWaitDialogCaption("Reset Layout...");
                string currentPath = "";
                System.IO.Stream streamLayout;
                foreach (GridView grv in this.ViewCollection)
                {
                    currentPath = IOHelper.CombinePath(_CURRENTDIRECTORY, String.Format("{0}_{1}.xml", _FormName, grv.Name));
                    if (File.Exists(currentPath))
                        File.Delete(currentPath);
                    streamLayout = new System.IO.MemoryStream();
                    streamLayout = listStreamLayout[grv.Name] as MemoryStream;
                    grv.RestoreLayoutFromStream(streamLayout);
                    streamLayout.Seek(0, System.IO.SeekOrigin.Begin);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Có lỗi xảy ra. Vui lòng liên hệ Người quản trị hệ thống để được hỗ trợ.");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
            finally
            {
                ViewManager.CloseWaitDialog();
            }
        }

        void SaveOriginalLayout()
        {
            try
            {
                System.IO.Stream streamLayout;
                listStreamLayout = new Hashtable();
                foreach (BaseView grv in this.ViewCollection)
                {
                    streamLayout = new System.IO.MemoryStream();
                    grv.SaveLayoutToStream(streamLayout);
                    streamLayout.Seek(0, System.IO.SeekOrigin.Begin);
                    if (listStreamLayout.ContainsKey(grv.Name) == false)
                        listStreamLayout.Add(grv.Name, streamLayout);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        void RestoreLayout()
        {
            try
            {
                string currentPath = "";
                string strXMLConfigColumnPath = string.Empty;
                foreach (BaseView grv in this.ViewCollection)
                {
                    currentPath = IOHelper.CombinePath(_CURRENTDIRECTORY, String.Format("{0}_{1}.xml", _FormName, grv.Name));
                    if (File.Exists(currentPath))
                        grv.RestoreLayoutFromXml(currentPath);
                }



            }
            catch (Exception ex)
            {
                MessageBox.Show("Có lỗi xảy ra. Vui lòng liên hệ Người quản trị hệ thống để được hỗ trợ.");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
        }

        void OnSaveLayout(object sender, EventArgs e)
        {
            SaveLayout();
        }

        void OnResetLayout(object sender, EventArgs e)
        {
            ResetLayout();
        }

        void OnExportData(object sender, EventArgs e)
        {
            string fileName = ShowSaveFileDialog("Microsoft Excel Document", "Microsoft Excel|*.xls");
            if (fileName != "")
            {
                //new ExportXlsProvider(fileName)
                //ExportTo(this.MainView as GridView, fileName);
                //ExportTo(fileName);
                string msg = "Do you want to export including details?";
                if (MessageBox.Show(msg, "", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    ExportTo(this.MainView as GridView, fileName);
                }
                else
                {
                    ExportToExcelWithoutDetail(this.MainView as GridView, fileName);
                }
                OpenFile(fileName);
            }
        }

        void OnExportToTextData(object sender, EventArgs e)
        {
            string fileName = ShowSaveFileDialog("Text Files", "Text Files|*.txt");
            if (fileName != "")
            {
                string msg = "Do you want to export including details?";
                if (MessageBox.Show(msg, "", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    ExportToText(this.MainView as GridView, fileName);
                }
                else
                {
                    ExportToTextWithoutDetail(this.MainView as GridView, fileName);
                }
                //ExportToText(this.MainView as GridView, fileName, false);
                OpenFile(fileName);
            }
        }

        private void OpenFile(string fileName)
        {
            if (MessageBox.Show("Do you want to open this file?" , "", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                try
                {
                    System.Diagnostics.Process process = new System.Diagnostics.Process();
                    process.StartInfo.FileName = fileName;
                    process.StartInfo.Verb = "Open";
                    process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
                    process.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Cannot find an application on your system suitable for openning the file with exported data.");
                    ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);                    
                }
            }
        }

        //IExportProvider provider
        private void ExportTo(GridView currentView, string fileName)
        {
            try
            {
                ViewManager.CreateWaitDialog();
                ViewManager.SetWaitDialogCaption("Exporting Data To Excel....");

                this.FindForm().Refresh();
                currentView.OptionsPrint.PrintDetails = true;
                currentView.OptionsPrint.ExpandAllDetails = true;
                currentView.OptionsPrint.ExpandAllGroups = true;
                currentView.OptionsPrint.AutoWidth = false;
                XlsExportOptions option = new XlsExportOptions();
                option.ShowGridLines = true;                
                currentView.ExportToXls(fileName, option);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Export data failed!");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
            finally
            {
                ViewManager.CloseWaitDialog();
            }
        }

        private void ExportToExcelWithoutDetail(GridView currentView, string fileName)
        {
            try
            {
                ViewManager.CreateWaitDialog();
                ViewManager.SetWaitDialogCaption("Exporting Data To Excel....");

                this.FindForm().Refresh();
                if (currentView == null) return;
                GridViewExportLink gvlink;
                using (ExportXlsProvider provider = new ExportXlsProvider(fileName))
                {
                    gvlink = (GridViewExportLink)currentView.CreateExportLink(provider);
                    gvlink.ExpandAll = true;
                    gvlink.ExportDetails = true;
                    gvlink.ExportAll = true;
                    gvlink.ExportTo(true);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Export data failed!");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
            finally
            {
                ViewManager.CloseWaitDialog();
            }
        }

        private void ExportTo(string fileName)
        {
            try
            {
                ViewManager.CreateWaitDialog();
                ViewManager.SetWaitDialogCaption("Exporting Data To Excel....");

                this.FindForm().Refresh();
                this.ExportToXls(fileName, true);

            }
            catch (Exception ex)
            {
                MessageBox.Show("Export data failed!");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
            finally
            {
                ViewManager.CloseWaitDialog();
            }
        }

        private void ExportToTextWithoutDetail(GridView currentView, string fileName)
        {
            try
            {
                ViewManager.CreateWaitDialog();
                ViewManager.SetWaitDialogCaption("Exporting Data To Text File....");

                this.FindForm().Refresh();
                GridViewExportLink gvlink;
                using (ExportTxtProvider provider = new ExportTxtProvider(fileName))
                {
                    gvlink = (GridViewExportLink)currentView.CreateExportLink(provider);
                    gvlink.ExpandAll = true;
                    gvlink.ExportDetails = true;
                    gvlink.ExportAll = true;
                    gvlink.ExportTo(true);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Export data failed!");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
            finally
            {
                ViewManager.CloseWaitDialog();
            }
        }

        private void ExportToText(GridView currentView, string fileName)
        {
            try
            {
                ViewManager.CreateWaitDialog();
                ViewManager.SetWaitDialogCaption("Exporting Data To Excel....");

                this.FindForm().Refresh();
                currentView.OptionsPrint.PrintDetails = true;
                currentView.OptionsPrint.ExpandAllDetails = true;
                currentView.OptionsPrint.ExpandAllGroups = true;
                currentView.OptionsPrint.AutoWidth = false;
                currentView.ExportToText(fileName,TextExportOptions.DefaultSeparator);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Export data failed!");
                ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
            }
            finally
            {
                ViewManager.CloseWaitDialog();
            }
        }

        private string ShowSaveFileDialog(string title, string filter)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            string name = Application.ProductName;
            int n = name.LastIndexOf(".") + 1;
            if (n > 0) name = name.Substring(n, name.Length - n);
            dlg.Title = "Export To " + title;
            //dlg.FileName = name;
            dlg.FileName = "filename";
            dlg.Filter = filter;
            if (dlg.ShowDialog() == DialogResult.OK) return dlg.FileName;
            return "";
        }


        #endregion

        #region Events
        void MyGridControl_LostFocus(object sender, EventArgs e)
        {
            if (isSaveLayout)
                SaveLayout();
        }

        void MyGridControl_Load(object sender, EventArgs e)
        {
            if (this.DesignMode)
            {
                return;
            }
            /******Layout*******/
            GetFormName();
            SaveOriginalLayout();
            if (isSaveLayout)
            {
                RestoreLayout();
            }
            /******End Layout*******/

            /*******Check Box All******/
            edit = new RepositoryItemCheckEdit();
            gvControl = this.MainView as GridView;
            if (gvControl.Columns.Count > 0)
            {
                gvControl.ShowGridMenu += gvControl_ShowGridMenu;
                if (gvControl.Columns[columnFieldNameAddCheckBox] != null)
                {
                    //columnFieldNameAddCheckBox = gvControl.Columns[columnAddCheckBox].FieldName;
                    gvControl.CustomDrawColumnHeader += MyGridControl_CustomDrawColumnHeader;
                    //gvControl.CustomDrawRowIndicator += new RowIndicatorCustomDrawEventHandler(gvControl_CustomDrawRowIndicator);
                    gvControl.MouseDown += MyGridControl_MouseDown;
                }
                //gvControl.CustomFilterDialog += gvControl_CustomFilterDialog;
            }
            if (GridLoad != null)
                GridLoad(sender, e);
            /*******End Check Box All******/



            //string strXMLConfigColumnPath = string.Empty;
            //GridHelper gh = new GridHelper();
            //foreach (BaseView grv in this.ViewCollection)
            //{
            //    strXMLConfigColumnPath = Application.StartupPath + "\\Config\\Columns\\Grid_" + _FormName + "_" + grv.Name + ".xml";
            //    if (File.Exists(strXMLConfigColumnPath))
            //    {
            //        gh.LoadColumnConfigFromXML(strXMLConfigColumnPath, gvControl);
            //    }
            //}



        }

        //void gvControl_CustomFilterDialog(object sender, CustomFilterDialogEventArgs e)
        //{
        //    if (_useCustomFilter == true)
        //    {
        //        GridView gv = sender as GridView;
        //        FrmAutoFilter frm = new FrmAutoFilter(this, e.Column);
        //        if (frm.ShowDialog() == DialogResult.OK)
        //        {
        //            e.FilterInfo = new ColumnFilterInfo(frm.Criteria);
        //        }
        //        else
        //        {
        //            e.FilterInfo = null;
        //        }
        //        e.Handled = true;
        //    }
        //}

        void gvControl_ShowGridMenu(object sender, GridMenuEventArgs e)
        {
            if (e.MenuType == GridMenuType.Column)
            {
                GridViewColumnMenu menu = e.Menu as GridViewColumnMenu;                

                // Add Save Layout menu
                Image img = Image.FromFile(IOHelper.CombinePath(IOHelper.ExecutePath, @"Images\save.png"));
                DXMenuItem item = new DXMenuItem("Save Layout", new EventHandler(OnSaveLayout), img.GetThumbnailImage(16, 16, null, IntPtr.Zero));
                item.BeginGroup = true;
                menu.Items.Add(item);

                // Add Reset Layout menu
                img = Image.FromFile(IOHelper.CombinePath(IOHelper.ExecutePath, @"Images\refresh.png"));
                menu.Items.Add(new DevExpress.Utils.Menu.DXMenuItem("Reset Layout", new EventHandler(OnResetLayout), img.GetThumbnailImage(16, 16, null, IntPtr.Zero)));

                // Add Export menu                 
                img = Image.FromFile(IOHelper.CombinePath(IOHelper.ExecutePath, @"Images\export1.png"));
                item = new DXMenuItem("Export To Excel", new EventHandler(OnExportData), img.GetThumbnailImage(16, 16, null, IntPtr.Zero));
                item.BeginGroup = true;
                menu.Items.Add(item);

                // Add Export To Text menu                 
                img = Image.FromFile(IOHelper.CombinePath(IOHelper.ExecutePath, @"Images\export2.png"));
                item = new DXMenuItem("Export To Text File", new EventHandler(OnExportToTextData), img.GetThumbnailImage(16, 16, null, IntPtr.Zero));
                menu.Items.Add(item);
            }
        }

        void imageResetLayout_Click(object sender, EventArgs e)
        {
            //MessageBox.Show("2.");
            ResetLayout();
        }

        void MyGridControl_MouseDown(object sender, MouseEventArgs e)
        {
            GridHitInfo info;
            Point pt = gvControl.GridControl.PointToClient(Control.MousePosition);
            info = gvControl.CalcHitInfo(pt);
            int checkboxX;
            int checkboxY;
            int x = checkboxX = info.HitPoint.X;
            int y = checkboxY = info.HitPoint.Y;

            // Reset Layout
            if (x >= minImageResetX && x <= maxImageResetX && y >= minImageResetY && y <= maxImageResetY)
            {
                imageResetLayout_Click(imageResetLayout, new EventArgs());
            }

            if (checkboxX >= minCheckBoxAllX && checkboxX <= maxCheckBoxAllX && checkboxY >= minCheckBoxAllY && checkboxY <= maxCheckBoxAllY && e.Button == MouseButtons.Left && info.Column == gvControl.Columns[columnFieldNameAddCheckBox])
            {
                CheckAllStatus = !checkboxState;
                gvControl.InvalidateColumnHeader(gvControl.Columns[columnFieldNameAddCheckBox]);
            }
        }

        void MyGridControl_CustomDrawColumnHeader(object sender, ColumnHeaderCustomDrawEventArgs e)
        {
            if (gvControl.Columns[columnFieldNameAddCheckBox] != null && e.Column == gvControl.Columns[columnFieldNameAddCheckBox] && isDisplayCheckBox)
            {
                try
                {
                    e.Info.InnerElements.Clear();
                    e.Painter.DrawObject(e.Info);
                    gvControl.Columns[columnFieldNameAddCheckBox].OptionsColumn.AllowSort = DevExpress.Utils.DefaultBoolean.False;
                    DrawCheckBox(e.Graphics, e.Bounds, checkboxState);
                    e.Handled = true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Có lỗi xảy ra. Vui lòng liên hệ Người quản trị hệ thống để được hỗ trợ.");
                    ExceptionHandler.LogWriter.Write(ex, ExceptionHandler.LOG_CAT_GENERAL);
                }
            }
        }

        private void gvControl_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e)
        {
            if (e.Info.Kind == DevExpress.Utils.Drawing.IndicatorKind.Header)
            {
                e.Painter.DrawObject(e.Info);
                DrawImageResetLayout(e.Graphics, e.Bounds);
                e.Handled = true;
                if (CustomDrawRowIndicator != null)
                    CustomDrawRowIndicator(sender, e);
            }
        }
        #endregion
    }
}
